#include "rpc-fs.h"
#include <dirent.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#define NSize 25000
#define MAX_STRING_SIZE 512
#define FILE_PACKAGE_LENGTH 512
#define CONF_FILE "conf_file"
#define ERROR -1
#define COMMENT '#'
#define ROOT "raiz"
#define OK 0
int isfirst = 1;
char cwd[NSize];

char * rls_1_svc(void *filler, struct svc_req *rq) {
    {
        // definimos el buffer donde cargaremos el contenido del directorio
        // y el arreglo donde guardamos el nombre del directorio de trabajo
        char buffer[NSize];

        // puntero que retornaremos como respuesta
        static char *dp;

        // 'vaciamos' el buffer para evitar devolver datos sucios
        int i = 0;
        for (; i < NSize; i++) {
            buffer[i] = '\0';
        }

        // si es la primera vez que se ejecuta la función,
        // seteamos el directorio de trabajo actual
        if (isfirst == 1) {
            isfirst = 0;
            getcwd(cwd, NSize);
        }


        // estructuras mediante las cuales leeeremos el contenido del directorio
        DIR *dp1;
        struct dirent *dirp;

        // abrimos el directorio
        dp1 = opendir(cwd);

        // si no se puede abrir el directorio...
        if (!dp1) {
            strcpy(buffer, "No se pudo leer el directorio.\n");
        } else {
            // leemos contenido del directorio y agregamos los nombres
            // de archivos o directorios al buffer, descartando el directorio
            // actual y el 'padre'
            while ((dirp = readdir(dp1)) != NULL) {
                if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0)
                    continue;
                if (strlen(buffer) != 0)
                    strcpy(&buffer[strlen(buffer)], "\n");
                strcpy(&buffer[strlen(buffer)], dirp->d_name);
                // si es un directorio, agrego [DIR] a la salida
                if (dirp->d_type == 0x004)
                    strcpy(&buffer[strlen(buffer)], " - [DIR]");

            }
            closedir(dp1);

            // si el buffer quedó vacio, no hay archivos ni directorios
            // que mostrar
            if (strlen(buffer) == 0) {
                strcpy(buffer, "Directorio vacio.\n");
            }

        }
        dp = buffer;
        return dp;
    }
}

char * rcd_1_svc(char * dir_name, struct svc_req *rq) {
    // si es la primera vez que se ejecuta la función,
    // seteamos el directorio de trabajo actual
    if (isfirst == 1) {
        isfirst = 0;
        getcwd(cwd, NSize);
    }

    static char res[MAX_STRING_SIZE];
    if (chdir(dir_name) == 0) {
        strcpy(res, "Se cambió correctamente el directorio.\nEl directorio actual es: ");
        getcwd(cwd, NSize);
        strcat(res, cwd);
        strcat(res, "\n");
    } else {
        strcpy(res, "No se pudo cambiar de directorio.\nUd. intentó cambiar a: ");
        strcat(res, dir_name);
        strcat(res, "\n");
    }
    return res;
}

get_output * get_1_svc(get_input * input, struct svc_req *rq) {
    static get_output *output;
    output = (get_output *) malloc(sizeof (get_output));
    FILE *file;
    file = fopen(input->file_name, "r");
    if (file == NULL) {
        output->count = ERROR;
    } else {
        fseek(file, input->count*FILE_PACKAGE_LENGTH, SEEK_SET);
        int ints_leidos = fread(output->bloque, sizeof (char), FILE_PACKAGE_LENGTH, file);

        output->count = ints_leidos;

        fclose(file);
    }
    return output;
}

int * put_1_svc(put_input * input, struct svc_req *rq) {
    static int i = ERROR;
    // puntero al archivo que se crea del lado del cliente
    FILE *file;
    // abro para crear o sobreescribir el archivo...
    if(input->count == 0)
        file = fopen(input->file_name, "w");
    // o para agregarle bloques subsiguientes
    else
        file = fopen(input->file_name, "a");

    if (file != NULL) {
        // escribo el bloque
        i = fwrite(input->data, sizeof (char), input->offset, file);
        fclose(file);
    } else
        i = EOF;

    return &i;
}

int read_conf(void) {
    char *buffer, *prop, *value;
    FILE *conf_file;

    // abrimos el archivo de configuración
    conf_file = fopen(CONF_FILE, "r");
    if (conf_file == NULL) {
        printf("No se puede leer el archivo de configuración.\n");
        return ERROR;
    }

    getcwd(cwd, NSize);

    buffer = (char *) malloc(sizeof (char) * MAX_STRING_SIZE);
    prop = (char *) malloc(sizeof (char) * MAX_STRING_SIZE);
    value = (char *) malloc(sizeof (char) * MAX_STRING_SIZE);

    // leemos el archivo linea a linea
    while (get_line(buffer, conf_file) != EOF) {

        // descarto los comentarios
        if (buffer[0] == COMMENT) {
            continue;
        }
        // 'tokenizo' la linea, por '='
        strcpy(prop, strtok(buffer, "="));
        strcpy(value, strtok(NULL, "="));

        //si es la especificacion del directorio raiz de trabajo
        if (strcasecmp(prop, ROOT) == 0) {

            int i = 0;
            if ((i = chdir(value)) == 0) {
                isfirst = 0;
                getcwd(cwd, NSize);
                printf("Directorio de trabajo: %s\n", cwd); //Muestra la carpeta pública
            }
        }
    }

    free(buffer);
    free(prop);
    free(value);

    fclose(conf_file);

    return OK;
}

int get_line(char Dest[], FILE *f) {
    int t = 0;
    char c;

    do {
        c = fgetc(f);
        if (c != '\n') Dest[t++] = c;
    } while (c != '\n' && c != EOF);
    Dest[t++] = '\0';
    if (t == 1)
        return get_line(Dest, f);
    else
        return c == EOF ? -1 : t - 1;
}